package cn.jtfadmin.codegen.utils;

import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.jtfadmin.base.data.jpa.service.JpaService;
import cn.jtfadmin.base.data.jpa.service.JpaTreeService;
import cn.jtfadmin.base.dict.dto.DictItemModelDTO;
import cn.jtfadmin.base.dict.service.DictEntityService;
import cn.jtfadmin.base.filesystem.annos.File;
import cn.jtfadmin.base.lang.common.domain.dto.*;
import cn.jtfadmin.base.lang.common.domain.entity.NamedTreeEntity;
import cn.jtfadmin.base.lang.common.domain.entity.TreeEntity;
import cn.jtfadmin.base.lang.common.service.BaseService;
import cn.jtfadmin.base.lang.common.service.BaseTreeService;
import cn.jtfadmin.base.lang.common.utils.AkUtils;
import cn.jtfadmin.base.lang.config.ApplicationHolder;
import cn.jtfadmin.base.lang.config.excel.ExcelWeb;
import cn.jtfadmin.base.lang.enums.FileType;
import cn.jtfadmin.codegen.domain.dto.*;
import cn.jtfadmin.codegen.domain.entity.CodeGenClassEntity;
import cn.jtfadmin.codegen.domain.entity.CodeGenFieldEntity;
import cn.jtfadmin.codegen.enums.FieldTypeEnum;
import cn.jtfadmin.codegen.enums.InputTypeEnum;
import cn.jtfadmin.codegen.service.CodeGenClassService;
import cn.jtfadmin.core.modules.sys.service.SysEnvActionService;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.support.JpaRepositoryImplementation;
import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.persistence.*;
import javax.validation.constraints.*;
import java.io.IOException;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.*;

/**
 * 代码生成工具
 * @author jtf
 * @since 0.0.2
 */
public class CodeGenUtils {


    private static boolean isIgnoreField(String fieldName){
        return Arrays.asList("id", "createDateTime","updateDateTime","createUserId","updateUserId").contains(fieldName);
    }
    private static void fillRequired(FieldDTO fieldDTO, CodeGenFieldEntity field){
        Set<String> importClassNames = fieldDTO.getImportClassNames();
        String fieldClassName = field.getFieldClassName();
        if(fieldClassName.equals(String.class.getName()) && ObjectUtils.defaultIfNull(field.getRequired(), false)) {
            fieldDTO.setNotBlank(true);
            importClassNames.add(NotBlank.class.getName());

        }else if(ObjectUtils.defaultIfNull(field.getRequired(), false)){
            fieldDTO.setNotNull(true);
            importClassNames.add(NotNull.class.getName());
        }
    }

    private static void fillBasicOrEnumSizeAndMinMax(FieldDTO fieldDTO, CodeGenFieldEntity field){
        Set<String> importClassNames = fieldDTO.getImportClassNames();
        String fieldClassName = field.getFieldClassName();
        if(fieldClassName.equals(String.class.getName())){
            Integer max = getInputLength(field.getMax());
            Integer min = getInputLength(field.getMin());
            if(Objects.nonNull(max)){
                fieldDTO.setSizeMax(max);
                importClassNames.add(Size.class.getName());
            }
            if(Objects.nonNull(min)){
                fieldDTO.setSizeMin(min);
                importClassNames.add(Size.class.getName());
            }
        }
        if(fieldClassName.equals(Integer.class.getName())
                || fieldClassName.equals(Long.class.getName())
        ){
            BigDecimal max = field.getMax();
            BigDecimal min = field.getMin();
            if(Objects.nonNull(max)){
                fieldDTO.setMax(max.intValue());
                importClassNames.add(Max.class.getName());
            }
            if(Objects.nonNull(min)){
                fieldDTO.setMin(min.intValue());
                importClassNames.add(Min.class.getName());
            }
        }
        if(fieldClassName.equals(BigDecimal.class.getName())){
            BigDecimal max = field.getMax();
            BigDecimal min = field.getMin();
            if(Objects.nonNull(max)){
                fieldDTO.setDecimalMax(max.toPlainString());
                importClassNames.add(DecimalMax.class.getName());

            }
            if(Objects.nonNull(min)){
                fieldDTO.setDecimalMin(min.toPlainString());
                importClassNames.add(DecimalMin.class.getName());
            }
        }
    }

    private static void fillFile(FieldDTO fieldDTO, CodeGenFieldEntity field){
        Set<String> importClassNames = fieldDTO.getImportClassNames();
        String fieldClassName = field.getFieldClassName();
        if(fieldClassName.equals(String.class.getName()) && StringUtils.hasText(field.getFileDir())){
            fieldDTO.setFileType(Objects.isNull(field.getFileType())? null : field.getFileType().name() );
            fieldDTO.setFileDir(field.getFileDir());
            fieldDTO.setFileNum(field.getFileNum());
            fieldDTO.setFileDescribe(field.getFileDescribe());
            importClassNames.add(File.class.getName());
            importClassNames.add(FileType.class.getName());
        }
    }

    private static void fillBasicFieldDTO(FieldDTO fieldDTO, CodeGenFieldEntity field){
        Set<String> importClassNames = fieldDTO.getImportClassNames();
        String fieldClassName = field.getFieldClassName();
        if(!fieldClassName.startsWith("java.lang")){
            importClassNames.add(fieldClassName);
        }
        fieldDTO.setFieldClass(getClassDTO(fieldClassName));
        fieldDTO.setComment(field.getComment());
        fieldDTO.setName(field.getName());
        if(!fieldClassName.startsWith("java.lang")){
            importClassNames.add(fieldClassName);
        }
        fillBasicOrEnumSizeAndMinMax(fieldDTO, field);
        fillRequired(fieldDTO, field);
        fillFile(fieldDTO, field);
    }

    private static FieldDTO fillCUDTO(CodeGenFieldEntity field){
        FieldDTO fieldDTO = new FieldDTO();
        String fieldClassName = field.getFieldClassName();
        fieldDTO.setFieldClass(getClassDTO(fieldClassName));
        fieldDTO.setComment(field.getComment());
        fieldDTO.setName(field.getName());
        fieldDTO.setFieldType(field.getFieldType());
        switch (field.getFieldType()){
            case BASIC:{
                fillBasicFieldDTO(fieldDTO, field);
                break;
            }case ENTITY:{
                fillRequired(fieldDTO, field);
                fieldDTO.setFieldClass(getClassDTO(String.class.getName()));
                fieldDTO.setComment(field.getComment()+" Id");
                fieldDTO.setName(AkUtils.megerFieldName(field.getName(), "id", false));
            }
            case COLLECTION:{
                fillRequired(fieldDTO, field);
                fieldDTO.setFieldClass(getClassDTO(String.class.getName()));
                fieldDTO.setComment(field.getComment()+" Ids");
                fieldDTO.setName(AkUtils.megerFieldName(field.getName(), "id", true));
            }
            case ENUM:{
                if(!fieldClassName.startsWith("java.lang")){
                    fieldDTO.getImportClassNames().add(fieldClassName);
                }
                fillRequired(fieldDTO, field);
            }
        }
        return fieldDTO;
    }
    /**
     * 将实体类转换为新增生成模板数据
     * @param entity 实体类
     * @return
     */
    public static AddTempDataDTO entityToAddTempData(CodeGenClassEntity entity){
        AddTempDataDTO dto = new AddTempDataDTO();
        Set<String> importClassNames = new HashSet<>();
        dto.setAddClass(getClassDTO(getClassDTO(entity.getClassName()).getPackageName().replace(".entity", "")

                +".dto."+getSubEntitySuffixName(entity.getClassName())+"AddPDTO"
        ));
        importClassNames.add(Serializable.class.getName());
        dto.setComment(entity.getComment());
        List<CodeGenFieldEntity> fields = entity.getFields();
        for (CodeGenFieldEntity field : fields) {
            if(field.getAddItem() ==null || !field.getAddItem()||isIgnoreField(field.getName())){
                continue;
            }
            FieldDTO fieldDTO = fillCUDTO(field);
            importClassNames.addAll(fieldDTO.getImportClassNames());
            dto.getFields().add(fieldDTO);
        }
        importClassNames.add(Getter.class.getName());
        importClassNames.add(Setter.class.getName());
        dto.getImportClass().addAll(importClassNames);
        Collections.sort(dto.getImportClass());
        return dto;
    }




    /**
     * 将实体类转换为编辑生成模板数据
     * @param entity 实体类
     * @return
     */
    public static EditTempDataDTO entityToEditTempData(CodeGenClassEntity entity){
        EditTempDataDTO dto = new EditTempDataDTO();
        Set<String> importClassNames = new HashSet<>();
        dto.setEditClass(getClassDTO(getClassDTO(entity.getClassName()).getPackageName().replace(".entity", "")

                +".dto."+getSubEntitySuffixName(entity.getClassName())+"EditPDTO"
        ));
        importClassNames.add(Serializable.class.getName());
        importClassNames.add(EditPDTO.class.getName());
        dto.setComment(entity.getComment());
        List<CodeGenFieldEntity> fields = entity.getFields();
        for (CodeGenFieldEntity field : fields) {
            if(field.getEditItem() ==null || !field.getEditItem() ||isIgnoreField(field.getName()) ){
                continue;
            }
            FieldDTO fieldDTO = fillCUDTO(field);
            importClassNames.addAll(fieldDTO.getImportClassNames());
            dto.getFields().add(fieldDTO);
        }
        importClassNames.add(NotBlank.class.getName());
        importClassNames.add(Getter.class.getName());
        importClassNames.add(Setter.class.getName());
        dto.getImportClass().addAll(importClassNames);
        Collections.sort(dto.getImportClass());
        return dto;
    }

    private static List<FieldDTO> fillModelModelDTO(CodeGenFieldEntity field) {
        switch (field.getFieldType()) {
            case BASIC:
            case ENUM: {
                return Arrays.asList(fillCUDTO(field));
            }
            case COLLECTION:
            case ENTITY: {
                String modelEmbed = field.getModelEmbed();
                if(!StringUtils.hasText(modelEmbed)){
                    return null;
                }
                CodeGenClassEntity childField = ApplicationHolder.getApplicationContext().getBean(CodeGenClassService.class).findRequiredOneByField("className", field.getFieldClassName());
                String[] modelEmbedArray = StringUtils.commaDelimitedListToStringArray(modelEmbed);
                List<FieldDTO> list = new ArrayList<>();
                for (String s : modelEmbedArray) {
                    for (CodeGenFieldEntity childFieldField : childField.getFields()) {
                        String childFieldFieldFieldClassName = childFieldField.getFieldClassName();
                        if (childFieldField.getName().equals(s)
                                && (childFieldField.getFieldType().equals(FieldTypeEnum.ENUM) || childFieldField.getFieldType().equals(FieldTypeEnum.BASIC))) {
                            FieldDTO fieldDTO = new FieldDTO();

                            fieldDTO.setFieldClass(getClassDTO(childFieldFieldFieldClassName));
                            fieldDTO.setComment(AkUtils.megerFieldCommont(field.getComment(), childFieldField.getComment()));
                            fieldDTO.setName(AkUtils.megerFieldName(field.getName(), childFieldField.getName(), FieldTypeEnum.COLLECTION.equals(field.getFieldType())));
                            fieldDTO.setFieldType(childFieldField.getFieldType());

                            switch (childFieldField.getFieldType()) {
                                case BASIC: {
                                    fillFile(fieldDTO, childFieldField);
                                }
                                case ENUM: {
                                    if (!childFieldFieldFieldClassName.startsWith("java.lang")) {
                                        fieldDTO.getImportClassNames().add(childFieldFieldFieldClassName);
                                    }
                                    break;
                                }
                            }
                            list.add(fieldDTO);
                        }

                    }

                }
                return list;

            }
            default:{
                return null;
            }
        }
    }

    private static List<FieldDTO> fillExcelModelDTO(CodeGenFieldEntity field) {
        switch (field.getFieldType()) {
            case BASIC:
            case ENUM: {
                return Arrays.asList(fillCUDTO(field));
            }
            case COLLECTION:
            case ENTITY: {
                String excelEmbed = field.getExcelEmbed();
                if(!StringUtils.hasText(excelEmbed)){
                    return null;
                }
                CodeGenClassEntity childField = ApplicationHolder.getApplicationContext().getBean(CodeGenClassService.class).findRequiredOneByField("className", field.getFieldClassName());
                String[] excelEmbedArray = StringUtils.commaDelimitedListToStringArray(excelEmbed);
                String excelEmbedId = field.getExcelEmbedId();
                List<FieldDTO> list = new ArrayList<>();
                for (String s : excelEmbedArray) {
                    for (CodeGenFieldEntity childFieldField : childField.getFields()) {
                        String childFieldFieldFieldClassName = childFieldField.getFieldClassName();
                        if (childFieldField.getName().equals(s)
                                && (childFieldField.getFieldType().equals(FieldTypeEnum.ENUM) || childFieldField.getFieldType().equals(FieldTypeEnum.BASIC))) {
                            FieldDTO fieldDTO = new FieldDTO();

                            fieldDTO.setFieldClass(getClassDTO(childFieldFieldFieldClassName));
                            fieldDTO.setComment(AkUtils.megerFieldCommont(field.getComment(), childFieldField.getComment()));
                            fieldDTO.setName(AkUtils.megerFieldName(field.getName(), childFieldField.getName(), FieldTypeEnum.COLLECTION.equals(field.getFieldType())));
                            fieldDTO.setFieldType(childFieldField.getFieldType());

                            switch (childFieldField.getFieldType()) {
                                case BASIC: {
                                    fillFile(fieldDTO, childFieldField);
                                }
                                case ENUM: {
                                    if (!childFieldFieldFieldClassName.startsWith("java.lang")) {
                                        fieldDTO.getImportClassNames().add(childFieldFieldFieldClassName);
                                    }
                                    break;
                                }


                                case COLLECTION:
                                case ENTITY: {
                                    fieldDTO.setFieldClass(getClassDTO(String.class.getName()));
                                    break;
                                }
                            }
                            if (s.equals(excelEmbedId)) {
                                if (childFieldFieldFieldClassName.equals(String.class.getName())) {
                                    fieldDTO.setNotBlank(true);
                                    fieldDTO.getImportClassNames().add(NotBlank.class.getName());

                                } else {
                                    fieldDTO.setNotNull(true);
                                    fieldDTO.getImportClassNames().add(NotNull.class.getName());
                                }
                            }
                            list.add(fieldDTO);
                        }

                    }

                }
                return list;

            }
            default:{
                return null;
            }
        }
    }


    /**
     * 将实体类转换为excel生成模板数据
     * @param entity 实体类
     * @return
     */
    public static ExcelTempDataDTO entityToExcelTempData(CodeGenClassEntity entity){
        ExcelTempDataDTO dto = new ExcelTempDataDTO();
        Set<String> importClassNames = new HashSet<>();
        importClassNames.add(Excel.class.getName());
        dto.setExcelClass(getClassDTO(getClassDTO(entity.getClassName()).getPackageName().replace(".entity", "")

                +".dto."+getSubEntitySuffixName(entity.getClassName())+"ExcelDTO"
        ));
        importClassNames.add(Serializable.class.getName());
        importClassNames.add(BaseExcelModalDTO.class.getName());
        dto.setComment(entity.getComment());
        List<CodeGenFieldEntity> fields = entity.getFields();
        for (CodeGenFieldEntity field : fields) {
            if((field.getExcelItem() !=null && field.getExcelItem()) ||StringUtils.hasText(field.getExcelEmbed())){
                List<FieldDTO> fieldDTOS = fillExcelModelDTO(field);
                if(fieldDTOS !=null){
                    dto.getFields().addAll(fieldDTOS);
                    for (FieldDTO fieldDTO : fieldDTOS) {
                        dto.getImportClass().addAll(fieldDTO.getImportClassNames());
                    }

                }
            }


        }
        importClassNames.add(Getter.class.getName());
        importClassNames.add(Setter.class.getName());
        dto.getImportClass().addAll(importClassNames);
        Collections.sort(dto.getImportClass());
        return dto;
    }


    public static ControllerTempDataDTO entityToControllerTempData(CodeGenClassEntity entity, ServiceTempDataDTO serviceTempDataDTO,
                                                                   AddTempDataDTO addTempDataDTO, EditTempDataDTO editTempDataDTO,
                                                                   ModelTempDataDTO modelTempDataDTO){
        ControllerTempDataDTO dto = new ControllerTempDataDTO();
        Set<String> importClassNames = new HashSet<>();
        dto.setControllerClass(getClassDTO(getClassDTO(entity.getClassName()).getPackageName().replace(".domain.entity", "")

                +".controller."+getSubEntitySuffixName(entity.getClassName())+"Controller"
        ));
        dto.setModelClass(modelTempDataDTO.getModelClass());
        dto.setComment(entity.getComment());
        dto.setEntityClass(getClassDTO(entity.getClassName()));
        dto.setServiceClass(serviceTempDataDTO.getServiceClass());
        dto.setAddClass(addTempDataDTO.getAddClass());

        dto.setEditClass(editTempDataDTO.getEditClass());
        Set<String> interfaceClassNames = StringUtils.commaDelimitedListToSet(entity.getInterfaceClassNames());
        if(interfaceClassNames.contains(TreeEntity.class.getName())
                || interfaceClassNames.contains(NamedTreeEntity.class.getName())){
           dto.setTreeFlag(true);
           importClassNames.add(TreeRDTO.class.getName());
            importClassNames.add(AntdvTreeDataRDTO.class.getName());
            importClassNames.add(SpecPDTO.class.getName());
        }else {
           dto.setTreeFlag(false);
            importClassNames.add(DictItemModelDTO.class.getName());
            importClassNames.add(PageRDTO.class.getName());
            importClassNames.add(SpecPagePDTO.class.getName());
        }
        importClassNames.add(addTempDataDTO.getAddClass().getClassName());
        importClassNames.add(editTempDataDTO.getEditClass().getClassName());
        importClassNames.add(RestController.class.getName());
        importClassNames.add(Validated.class.getName());
        importClassNames.add(Autowired.class.getName());
        importClassNames.add(entity.getClassName());
        importClassNames.add(serviceTempDataDTO.getServiceClass().getClassName());
        importClassNames.add(GetMapping.class.getName());
        importClassNames.add(PostMapping.class.getName());
        importClassNames.add(PutMapping.class.getName());
        importClassNames.add(DeleteMapping.class.getName());
        importClassNames.add(List.class.getName());
        importClassNames.add(modelTempDataDTO.getModelClass().getClassName());
        importClassNames.add(SpecPDTO.class.getName());
        importClassNames.add(RequestBody.class.getName());
        importClassNames.add(NotBlank.class.getName());
        importClassNames.add(ResultDTO.class.getName());
        importClassNames.add(RequestParam.class.getName());
        importClassNames.add(SpecPDTO.class.getName());
        importClassNames.add(MultipartFile.class.getName());
        importClassNames.add(IOException.class.getName());
        importClassNames.add(ExcelWeb.class.getName());

        dto.setUrlPrefix(entity.getUrlPrefix());
        dto.getImportClass().addAll(importClassNames);
        Collections.sort(dto.getImportClass());
        return dto;
    }


    public static ModelTempDataDTO entityToModelTempData(CodeGenClassEntity entity){
        ModelTempDataDTO dto = new ModelTempDataDTO();
        Set<String> importClassNames = new HashSet<>();
        dto.setModelClass(getClassDTO(getClassDTO(entity.getClassName()).getPackageName().replace(".entity", "")

                +".dto."+getSubEntitySuffixName(entity.getClassName())+"ModelDTO"
        ));
        importClassNames.add(Serializable.class.getName());
        importClassNames.add(BaseEntityDTO.class.getName());
        dto.setComment(entity.getComment());
        List<CodeGenFieldEntity> fields = entity.getFields();
        for (CodeGenFieldEntity field : fields) {
            if(field.getFieldType().equals(FieldTypeEnum.COLLECTION) || field.getFieldType().equals(FieldTypeEnum.ENTITY)){
                List<FieldDTO> fieldDTOs = fillModelModelDTO(field);
                if(fieldDTOs != null){
                    dto.getFields().addAll(fieldDTOs);
                }
            }else if(field.getModelItem() ==null || !field.getModelItem() ||isIgnoreField(field.getName())){
                continue;
            }else {
                List<FieldDTO> fieldDTOs = fillModelModelDTO(field);
                if(fieldDTOs != null){
                    dto.getFields().addAll(fieldDTOs);
                }
            }

        }
        for (FieldDTO field : dto.getFields()) {
            dto.getImportClass().addAll(field.getImportClassNames());
        }
        importClassNames.add(Getter.class.getName());
        importClassNames.add(Setter.class.getName());
        dto.getImportClass().addAll(importClassNames);
        dto.setImportClass(new ArrayList<>(new HashSet<>(dto.getImportClass())));
        Collections.sort(dto.getImportClass());
        return dto;
    }

    public static boolean isTreeEntity(String className){
        CodeGenClassEntity entity = ApplicationHolder.getApplicationContext().getBean(CodeGenClassService.class).findRequiredOneByField("className", className);
        Set<String> interfaceClassNames = StringUtils.commaDelimitedListToSet(entity.getInterfaceClassNames());
        if(interfaceClassNames.contains(TreeEntity.class.getName())
                || interfaceClassNames.contains(NamedTreeEntity.class.getName())){
            return true;
        }
        return false;
    }

    public static VueModalTemDataDTO entityToVueMadalTemData(CodeGenClassEntity entity){
        String entitySimpleName = getClassDTO(entity.getClassName()).getClassSimpleName().replace("Entity", "");
        VueModalTemDataDTO dto = new VueModalTemDataDTO();
        dto.setEntityClass(getClassDTO(entity.getClassName()));
        dto.setName(entitySimpleName+"Modal");
        dto.setDescription(entity.getComment()+"新增编辑页面");
        Set<String> importUrlSet = new HashSet<>();
        importUrlSet.add(entitySimpleName+"Url");
        dto.getUrlMap().put("url", entitySimpleName+"Url");
        List<CodeGenFieldEntity> fields = entity.getFields();
        for (CodeGenFieldEntity field : fields) {
            Boolean addItem = field.getAddItem();
            Boolean editItem = field.getEditItem();
            if(ObjectUtils.defaultIfNull(addItem,false)|| ObjectUtils.defaultIfNull(editItem, false)){
                FieldTypeEnum fieldType = field.getFieldType();
                InputTypeEnum inputType = field.getInputType();
                switch (fieldType){
                    case BASIC:{
                        switch (inputType){
                            case TEXT_AREA:{
                                dto.getFields().add(new VueModalTemDataDTO.FieldDTO(field.getComment(), "a-textarea", getInputTagParam(field), getFormTag(field)));
                                break;
                            }
                            case RICH_TEXT:{
                                dto.setHasRichText(true);
                                dto.getFields().add(new VueModalTemDataDTO.FieldDTO(field.getComment(), "AkEditor", getInputTagParam(field), getFormTag(field)));
                                dto.getImportComNames().add("AkEditor");
                                dto.getImportComs().add("import AkEditor from \"../../../components/akfh/AkEditor\";");
                                break;
                            }
                            case TEXT:{
                                dto.getFields().add(new VueModalTemDataDTO.FieldDTO(field.getComment(), "a-input", getInputTagParam(field), getFormTag(field)));
                                break;
                            }
                            case File:{
                                dto.getFields().add(new VueModalTemDataDTO.FieldDTO(field.getComment(), "AkUpload", getFileTagParam(field), getFormTag(field)));
                                dto.getImportComNames().add("AkUpload");
                                dto.getImportComs().add("import AkUpload from \"../../../components/akfh/AkUpload\";");
                                break;
                            }
                            case BIGDECIMAL:{
                                dto.getFields().add(new VueModalTemDataDTO.FieldDTO(field.getComment(), "a-input-number", getDecimalTagParam(field), getFormTag(field)));
                                break;
                            }
                            case NUMBER:{
                                dto.getFields().add(new VueModalTemDataDTO.FieldDTO(field.getComment(), "a-input-number", getNumTagParam(field), getFormTag(field)));
                                break;
                            }
                            case TIME:{
                                dto.getFields().add(new VueModalTemDataDTO.FieldDTO(field.getComment(), "AkTimePicker", getTagDecorator(field.getName(), field.getRequired(),null,null, null, field.getUnique()), getFormTag(field)));
                                dto.getImportComNames().add("AkTimePicker");
                                dto.getImportComs().add("import AkTimePicker from \"../../../components/akfh/AkTimePicker\";");
                                break;
                            }
                            case DATE_TIME:{
                                dto.getFields().add(new VueModalTemDataDTO.FieldDTO(field.getComment(), "AkDateTimePicker", getTagDecorator(field.getName(), field.getRequired(),null,null, null, field.getUnique()), getFormTag(field)));
                                dto.getImportComNames().add("AkDateTimePicker");
                                dto.getImportComs().add("import AkDateTimePicker from \"../../../components/akfh/AkDateTimePicker\";");
                                break;
                            }case DATE:{
                                dto.getFields().add(new VueModalTemDataDTO.FieldDTO(field.getComment(), "AkDatePicker", getTagDecorator(field.getName(), field.getRequired(),null,null, null, field.getUnique()), getFormTag(field)));
                                dto.getImportComNames().add("AkDatePicker");
                                dto.getImportComs().add("import AkDatePicker from \"../../../components/akfh/AkDatePicker\";");
                            }
                        }
                        break;
                    }case ENUM:{
                        switch (inputType){
                            case RADIO:{
                                dto.getFields().add(new VueModalTemDataDTO.FieldDTO(field.getComment(), "AkDictRadio", "dictCode=\""+getClassSimpleName(field.getFieldClassName())+"\""+getTagDecorator(field.getName(), field.getRequired(),null,null, null, field.getUnique()), getFormTag(field)));
                                dto.getImportComNames().add("AkDictRadio");
                                dto.getImportComs().add("import AkDictRadio from \"../../../components/akfh/AkDictRadio\";");
                                break;
                            }
                            case SELECT:{
                                dto.getFields().add(new VueModalTemDataDTO.FieldDTO(field.getComment(), "AkDictSelectTag", "dictCode=\""+getClassSimpleName(field.getFieldClassName())+"\""+getTagDecorator(field.getName(), field.getRequired(),null,null, null, field.getUnique()), getFormTag(field)));
                                dto.getImportComNames().add("AkDictSelectTag");
                                dto.getImportComs().add("import AkDictSelectTag from \"../../../components/akfh/AkDictSelectTag\";");
                                break;
                            }
                        }
                        break;
                    }
                    case ENTITY:{

                        String fieldSimpleNameUrl = getClassDTO(field.getFieldClassName()).getClassSimpleName().replace("Entity", "")+"Url";
                        dto.getUrlMap().put(fieldSimpleNameUrl,fieldSimpleNameUrl);
                        importUrlSet.add(fieldSimpleNameUrl);
                        switch (inputType){
                            case RADIO:{
                                dto.getFields().add(new VueModalTemDataDTO.FieldDTO(field.getComment(), "AkRadio", ":url=\"`${"+fieldSimpleNameUrl+".named}?columns="+field.getShowColumnName()+"`\" "+getTagDecorator(field.getName()+"Id", field.getRequired(),null,null, null, null), getFormTag(field)));
                                dto.getImportComNames().add("AkRadio");
                                dto.getImportComs().add("import AkRadio from \"../../../components/akfh/AkRadio\";");
                                break;
                            }
                            case SELECT:{
                                boolean treeEntity = isTreeEntity(field.getFieldClassName());
                                if(treeEntity){
                                    dto.getFields().add(new VueModalTemDataDTO.FieldDTO(field.getComment(), "AkTreeSelect", ":url=\"`${"+fieldSimpleNameUrl+".tree}?columns="+field.getShowColumnName()+"`\" "+getTagDecorator(field.getName()+"Id", field.getRequired(),null,null, null, null), getFormTag(field)));
                                    dto.getImportComNames().add("AkTreeSelect");
                                    dto.getImportComs().add("import AkTreeSelect from \"../../../components/akfh/AkTreeSelect\";");
                                    break;
                                }else {
                                    dto.getFields().add(new VueModalTemDataDTO.FieldDTO(field.getComment(), "AkSelectTag", ":url=\"`${"+fieldSimpleNameUrl+".named}?columns="+field.getShowColumnName()+"`\" "+getTagDecorator(field.getName()+"Id", field.getRequired(),null,null, null, null), getFormTag(field)));
                                    dto.getImportComNames().add("AkSelectTag");
                                    dto.getImportComs().add("import AkSelectTag from \"../../../components/akfh/AkSelectTag\";");
                                    break;
                                }

                            }
                        }
                        break;
                    }case COLLECTION:{
                        String fieldSimpleNameUrl = getClassDTO(field.getFieldClassName()).getClassSimpleName().replace("Entity", "")+"Url";
                        dto.getUrlMap().put(fieldSimpleNameUrl,fieldSimpleNameUrl);
                        importUrlSet.add(fieldSimpleNameUrl);
                        switch (inputType){
                            case CHECKBOX:{
                                dto.getFields().add(new VueModalTemDataDTO.FieldDTO(field.getComment(), "AkCheckbox", ":url=\"`${"+fieldSimpleNameUrl+".named}?columns="+field.getShowColumnName()+"`\" "+getTagDecorator(field.getName()+"Ids", field.getRequired(),null,null, null, null), getFormTag(field)));
                                dto.getImportComNames().add("AkCheckbox");
                                dto.getImportComs().add("import AkCheckbox from \"../../../components/akfh/AkCheckbox\";");
                                break;
                            }
                            case SELECT_MU:{
                                boolean treeEntity = isTreeEntity(field.getFieldClassName());
                                if(treeEntity){
                                    dto.getFields().add(new VueModalTemDataDTO.FieldDTO(field.getComment(), "AkTreeSelectMultiple", ":url=\"`${"+fieldSimpleNameUrl+".tree}?columns="+field.getShowColumnName()+"`\" "+getTagDecorator(field.getName()+"Ids", field.getRequired(),null,null, null, null), getFormTag(field)));
                                    dto.getImportComNames().add("AkTreeSelectMultiple");
                                    dto.getImportComs().add("import AkTreeSelectMultiple from \"../../../components/akfh/AkTreeSelectMultiple\";");
                                    break;
                                }else {
                                    dto.getFields().add(new VueModalTemDataDTO.FieldDTO(field.getComment(), "AkSelectMultipleTag", ":url=\"`${"+fieldSimpleNameUrl+".named}?columns="+field.getShowColumnName()+"`\" "+getTagDecorator(field.getName()+"Ids", field.getRequired(),null,null, null, null), getFormTag(field)));
                                    dto.getImportComNames().add("AkSelectMultipleTag");
                                    dto.getImportComs().add("import AkSelectMultipleTag from \"../../../components/akfh/AkSelectMultipleTag\";");
                                    break;
                                }
                            }
                        }
                        break;
                    }
                }
            }
        }
        dto.setUrls(StringUtils.collectionToCommaDelimitedString(importUrlSet));
        return dto;
    }


    private static Integer getInputLength(BigDecimal length){
        if(length == null){
            return null;
        }
        return length.intValue();
    }


    private static BigDecimal getDecimalStep(BigDecimal max, BigDecimal min){
        Integer n = null;
        if(Objects.nonNull(max)){
            String maxStr = max.toPlainString();
            int j = maxStr.lastIndexOf(".");
            int n1 = j<0?0:maxStr.substring(j+1).length();
            n = n1;
        }
        if(Objects.nonNull(min)){
            String minStr = min.toPlainString();
            if(minStr.startsWith("-")){
                minStr = minStr.substring(1);
            }
            int j = minStr.lastIndexOf(".");
            int n1 = j<0?0:minStr.substring(j+1).length();
            if(Objects.isNull(n) || n< n1){
                n = n1;
            }
        }
        if(n!=null){
            BigDecimal result = BigDecimal.ZERO;
            for (int i = 0; i < n; i++) {
                result.multiply(new BigDecimal("0.1"));
            }
            return result;
        }
        return null;
    }

    private static String getNumTagParam(CodeGenFieldEntity field){
        StringBuilder stringBuilder = new StringBuilder();
        if(field.getMax()!=null){
            stringBuilder.append(":max=\""+field.getMax().intValue()+"\" ");
        }
        if(field.getMin()!=null){
            stringBuilder.append(":min=\""+field.getMin().intValue()+"\" ");
        }
        stringBuilder.append(getTagDecorator(field.getName(), field.getRequired(),null,null, null, field.getUnique()));
        return stringBuilder.toString();
    }
    private static String getDecimalTagParam(CodeGenFieldEntity field){
        StringBuilder stringBuilder = new StringBuilder();
        if(field.getMax()!=null){
            stringBuilder.append(":max=\""+field.getMax().toPlainString()+"\" ");
        }
        if(field.getMin()!=null){
            stringBuilder.append(":min=\""+field.getMin().toPlainString()+"\" ");
        }
        BigDecimal decimalStep = getDecimalStep(field.getMax(), field.getMin());
        if(decimalStep != null){
            stringBuilder.append(":step=\""+decimalStep.toPlainString()+"\" ");
        }
        stringBuilder.append(getTagDecorator(field.getName(), field.getRequired(),null,null, null, field.getUnique()));
        return stringBuilder.toString();
    }

    private static String getFileTagParam(CodeGenFieldEntity field){
        return new StringBuilder("type=\""+field.getFileDir()+"\" :fileLength=\""+ObjectUtils.defaultIfNull(field.getFileNum(), 10)+"\" ")
                .append(":updateFileName=\""+ObjectUtils.defaultIfNull(field.getFileUpdateName(), false)+"\" ")
                .append(getTagDecorator(field.getName(),
                        field.getRequired(),
                        getInputLength(field.getMax()),
                        getInputLength(field.getMin()),
                        null,
                        field.getUnique()
                ))
                .toString();
    }



    private static String getFormTag(CodeGenFieldEntity field){
        Boolean addItem = ObjectUtils.defaultIfNull(field.getAddItem(),false);
        Boolean editItem = ObjectUtils.defaultIfNull(field.getEditItem(), false);
        if(addItem && editItem){
            return "";
        }else if(addItem){
            return "v-if=\"!model.id\"";
        }else {
            return "v-if=\"!!model.id\"";
        }
    }

    private static String getInputTagParam(CodeGenFieldEntity field){
        StringBuilder stringBuilder =  new StringBuilder();
         return stringBuilder.append("autocomplete=\"off\" ")
                 .append(
                         getTagDecorator(field.getName(),
                                 field.getRequired(),
                                 getInputLength(field.getMax()),
                                 getInputLength(field.getMin()),
                                 null,
                                 field.getUnique()
                                 )
                 )
                .toString();
    }



    private static String getTagDecorator(String name, Boolean required, Integer max, Integer min, String pattern, Boolean dulicate){
        StringBuilder stringBuilder =  new StringBuilder();
        return stringBuilder.append("v-decorator=\"['")
                .append(name)
                .append("', {rules:getValidator(")
                .append(required)
                .append(", ")
                .append(max)
                .append(", ")
                .append(min)
                .append(", ")
                .append(pattern)
                .append(", ")
                .append(dulicate)
                .append(")}]\"")
                .toString();
    }

    public static VueListTemDataDTO entityToVueListTemData(CodeGenClassEntity entity){
        VueListTemDataDTO dto = new VueListTemDataDTO();
        Set<String> importUrlSet = new HashSet<>();
        String entitySimpleName = getClassDTO(entity.getClassName()).getClassSimpleName().replace("Entity", "");
        String module = ApplicationHolder.getApplicationContext().getBean(SysEnvActionService.class).getValue(CodeGenClassService.MODULE_KEY);
        dto.setName(entitySimpleName+"List");
        dto.setDescription(entity.getComment()+"列表页面");
        dto.setAddPerm(module+":"+entitySimpleName+":add");
        dto.setImportPerm(module+":"+entitySimpleName+":import");
        dto.setEditPerm(module+":"+entitySimpleName+":edit");
        dto.setDelPerm(module+":"+entitySimpleName+":del");
        dto.setModalTag(entitySimpleName+"Modal");
        importUrlSet.add(entitySimpleName+"Url");
        dto.getUrlMap().put("url", entitySimpleName+"Url");
        for (CodeGenFieldEntity field : entity.getFields()) {
            FieldTypeEnum fieldType = field.getFieldType();
            switch (fieldType){
                case BASIC:{
                    InputTypeEnum inputType = field.getInputType();
                    if(ObjectUtils.defaultIfNull(field.getListItem(),false)){
                        Map<String,  String> map = new HashedMap();
                        map.put("title","\""+field.getComment()+"\"");
                        map.put("align","\"center\"");
                        dto.getColumns().add(map);
                        switch (inputType){
                            case DATE:
                            case DATE_TIME:
                            case TIME:
                            case BIGDECIMAL:
                            case NUMBER:{
                                map.put("dataIndex","\""+field.getName()+"\"");
                                break;
                            }
                            case File:{
                                map.put("dataIndex","\""+field.getName()+"_fileUrl\"");
                                map.put("scopedSlots","{ customRender: 'file' }");
                                break;
                            }
                            case TEXT:
                            case TEXT_AREA:{
                                map.put("dataIndex","\""+field.getName()+"\"");
                                map.put("scopedSlots","{ customRender: 'ellipsis' }");
                                break;
                            }
                            case RICH_TEXT:{
                                map.put("dataIndex","\""+field.getName()+"\"");
                                map.put("scopedSlots","{ customRender: 'richtext' }");
                                break;
                            }

                        }
                    }
                    if(ObjectUtils.defaultIfNull(field.getSelectItem(),false)){
                        switch (inputType){
                            case DATE:{
                                dto.getQueryParams().add(
                                        new VueListTemDataDTO.QueryParamDTO(
                                                Arrays.asList(field.getName()+"_ge",field.getName()+"_le" ),
                                                field.getComment(),
                                                "AkDatePicker",
                                                ""
                                        ));
                                dto.getQueryParamMap().put(field.getName()+"_ge", new SpecConditionDTO("ge", "", field.getName()));
                                dto.getQueryParamMap().put(field.getName()+"_le", new SpecConditionDTO("le", "", field.getName()));
                                dto.getImportComNames().add("AkDatePicker");
                                dto.getImportComs().add("import AkDatePicker from '../../components/akfh/AkDatePicker';");
                                break;
                            }
                            case DATE_TIME:{
                                dto.getQueryParams().add(
                                        new VueListTemDataDTO.QueryParamDTO(
                                                Arrays.asList(field.getName()+"_ge",field.getName()+"_le" ),
                                                field.getComment(),
                                                "AkDateTimePicker",
                                                ""
                                        ));
                                dto.getQueryParamMap().put(field.getName()+"_ge", new SpecConditionDTO("ge", "", field.getName()));
                                dto.getQueryParamMap().put(field.getName()+"_le", new SpecConditionDTO("le", "", field.getName()));
                                dto.getImportComNames().add("AkDateTimePicker");
                                dto.getImportComs().add("import AkDateTimePicker from '../../components/akfh/AkDateTimePicker';");
                                break;
                            }
                            case TIME:{
                                dto.getQueryParams().add(
                                        new VueListTemDataDTO.QueryParamDTO(
                                                Arrays.asList(field.getName()+"_ge",field.getName()+"_le" ),
                                                field.getComment(),
                                                "AkTimePicker",
                                                ""
                                        ));
                                dto.getQueryParamMap().put(field.getName()+"_ge", new SpecConditionDTO("ge", "", field.getName()));
                                dto.getQueryParamMap().put(field.getName()+"_le", new SpecConditionDTO("le", "", field.getName()));
                                dto.getImportComNames().add("AkTimePicker");
                                dto.getImportComs().add("import AkTimePicker from '../../components/akfh/AkTimePicker';");
                                break;
                            }
                            case BIGDECIMAL: {
                                BigDecimal decimalStep = getDecimalStep(field.getMax(), field.getMin());

                                dto.getQueryParams().add(
                                        new VueListTemDataDTO.QueryParamDTO(
                                                Arrays.asList(field.getName()+"_ge",field.getName()+"_le" ),
                                                field.getComment(),
                                                "a-input-number",
                                                Objects.isNull(decimalStep)?"":":step=\""+decimalStep.toPlainString()+"\""
                                        ));
                                dto.getQueryParamMap().put(field.getName()+"_ge", new SpecConditionDTO("ge", "", field.getName()));
                                dto.getQueryParamMap().put(field.getName()+"_le", new SpecConditionDTO("le", "", field.getName()));
                                break;
                            }
                            case NUMBER:{

                                dto.getQueryParams().add(
                                        new VueListTemDataDTO.QueryParamDTO(
                                                Arrays.asList(field.getName()+"_ge",field.getName()+"_le" ),
                                                field.getComment(),
                                                "a-input-number",
                                                ""
                                        ));
                                dto.getQueryParamMap().put(field.getName()+"_ge", new SpecConditionDTO("ge", "", field.getName()));
                                dto.getQueryParamMap().put(field.getName()+"_le", new SpecConditionDTO("le", "", field.getName()));
                                break;
                            }

                            case TEXT:
                            case TEXT_AREA:
                            case RICH_TEXT:{
                                dto.getQueryParams().add(
                                        new VueListTemDataDTO.QueryParamDTO(
                                                Arrays.asList(field.getName() ),
                                                field.getComment(),
                                                "a-input",
                                                ""
                                        ));
                                dto.getQueryParamMap().put(field.getName(), new SpecConditionDTO("like", "", field.getName()));
                                break;
                            }

                        }
                    }
                    break;
                }case ENUM:{
                    if(ObjectUtils.defaultIfNull(field.getListItem(),false)){
                        Map<String,  String> map = new HashedMap();
                        map.put("title","\""+field.getComment()+"\"");
                        map.put("align","\"center\"");
                        map.put("dataIndex","\""+field.getName()+"_dictText\"");
                        dto.getColumns().add(map);
                    }
                    if(ObjectUtils.defaultIfNull(field.getSelectItem(),false)){
                        dto.getQueryParams().add(
                                new VueListTemDataDTO.QueryParamDTO(
                                        Arrays.asList(field.getName()),
                                        field.getComment(),
                                        "AkDictSelectMultipleTag",
                                        "dictCode=\""+getClassDTO(field.getFieldClassName()).getClassSimpleName()+"\""
                                ));
                        dto.getQueryParamMap().put(field.getName(), new SpecConditionDTO("in", "", field.getName()));
                        dto.getImportComNames().add("AkDictSelectMultipleTag");
                        dto.getImportComs().add("import AkDictSelectMultipleTag from '../../components/akfh/AkDictSelectMultipleTag';");
                    }
                    break;
                }
                case COLLECTION:
                case ENTITY:{
                    boolean collectionFlag = fieldType.equals(FieldTypeEnum.COLLECTION);
                    if(StringUtils.hasText(field.getListEmbed())){
                        String listEmbed = field.getListEmbed();
                        String[] listEmbedArray = StringUtils.commaDelimitedListToStringArray(listEmbed);

                        String fieldClassName = field.getFieldClassName();
                        CodeGenClassEntity child = ApplicationHolder.getApplicationContext()
                                .getBean(CodeGenClassService.class).findRequiredOneByField("className", fieldClassName);
                        for (String listEmbedStr : listEmbedArray) {
                            for (CodeGenFieldEntity childField : child.getFields()) {
                                if(!childField.getName().equals(listEmbedStr)) {
                                    continue;
                                }
                                String fieldName = AkUtils.megerFieldName(field.getName(),childField.getName(), collectionFlag);
                                String comment = AkUtils.megerFieldCommont(field.getComment(), childField.getComment());
                                switch (childField.getFieldType()){
                                    case BASIC:{
                                        Map<String,  String> map = new HashedMap();
                                        map.put("title","\""+comment+"\"");
                                        map.put("align","\"center\"");
                                        dto.getColumns().add(map);
                                        switch (childField.getInputType()) {
                                            case DATE:
                                            case DATE_TIME:
                                            case TIME:
                                            case BIGDECIMAL:
                                            case NUMBER: {
                                                map.put("dataIndex", "\"" + fieldName + "\"");
                                                break;
                                            }
                                            case File: {
                                                map.put("dataIndex", "\"" + fieldName + "_fileUrl\"");
                                                map.put("scopedSlots", "{ customRender: 'file' }");
                                                break;
                                            }
                                            case TEXT:
                                            case TEXT_AREA: {
                                                map.put("dataIndex", "\"" + fieldName + "\"");
                                                map.put("scopedSlots", "{ customRender: 'ellipsis' }");
                                                break;
                                            }
                                            case RICH_TEXT: {
                                                map.put("dataIndex", "\"" + fieldName + "\"");
                                                map.put("scopedSlots", "{ customRender: 'richtext' }");
                                                break;
                                            }
                                        }
                                        break;
                                    }
                                    case ENUM:{
                                        Map<String,  String> map = new HashedMap();
                                        map.put("title","\""+comment+"\"");
                                        map.put("align","\"center\"");
                                        map.put("dataIndex", "\"" + fieldName + "_dictText\"");
                                        dto.getColumns().add(map);
                                        break;
                                    }

                                }
                            }
                        }
                    }
                    if(StringUtils.hasText(field.getSelectEmbed())){
                        String selectEmbed = field.getSelectEmbed();
                        String[] selectEmbedArray = StringUtils.commaDelimitedListToStringArray(selectEmbed);
                        String fieldClassName = field.getFieldClassName();
                        CodeGenClassEntity child = ApplicationHolder.getApplicationContext()
                                .getBean(CodeGenClassService.class).findRequiredOneByField("className", fieldClassName);
                        for (String selectEmbedStr : selectEmbedArray) {
                            for (CodeGenFieldEntity childField : child.getFields()) {
                                if(!childField.getName().equals(selectEmbedStr)) {
                                    continue;
                                }
                                String fieldName = AkUtils.megerFieldName(field.getName(),childField.getName(), collectionFlag);
                                String comment = AkUtils.megerFieldCommont(field.getComment(), childField.getComment());
                                if(childField.getFieldType().equals(FieldTypeEnum.ENUM)){
                                    dto.getQueryParams().add(
                                            new VueListTemDataDTO.QueryParamDTO(
                                                    Arrays.asList(fieldName),
                                                    comment,
                                                    "AkDictSelectMultipleTag",
                                                    "dictCode=\""+getClassDTO(childField.getFieldClassName()).getClassSimpleName()+"\""
                                            ));
                                    dto.getQueryParamMap().put(fieldName, new SpecConditionDTO("in", "", field.getName()+"."+childField.getName()));
                                    dto.getImportComNames().add("AkDictSelectMultipleTag");
                                    dto.getImportComs().add("import AkDictSelectMultipleTag from '../../components/akfh/AkDictSelectMultipleTag';");
                                }

                                switch (childField.getInputType()){
                                    case DATE:{
                                        dto.getQueryParams().add(
                                                new VueListTemDataDTO.QueryParamDTO(
                                                        Arrays.asList(fieldName+"_ge",fieldName+"_le" ),
                                                        comment,
                                                        "AkDatePicker",
                                                        ""
                                                ));
                                        dto.getQueryParamMap().put(fieldName+"_ge", new SpecConditionDTO("ge", "", field.getName()+"."+childField.getName()));
                                        dto.getQueryParamMap().put(fieldName+"_le", new SpecConditionDTO("le", "", field.getName()+"."+childField.getName()));
                                        dto.getImportComNames().add("AkDatePicker");
                                        dto.getImportComs().add("import AkDatePicker from '../../components/akfh/AkDatePicker';");
                                        break;
                                    }
                                    case DATE_TIME:{
                                        dto.getQueryParams().add(
                                                new VueListTemDataDTO.QueryParamDTO(
                                                        Arrays.asList(fieldName+"_ge",fieldName+"_le" ),
                                                        comment,
                                                        "AkDateTimePicker",
                                                        ""
                                                ));
                                        dto.getQueryParamMap().put(fieldName+"_ge", new SpecConditionDTO("ge", "", field.getName()+"."+childField.getName()));
                                        dto.getQueryParamMap().put(fieldName+"_le", new SpecConditionDTO("le", "", field.getName()+"."+childField.getName()));
                                        dto.getImportComNames().add("AkDatePicker");
                                        dto.getImportComs().add("import AkDateTimePicker from '../../components/akfh/AkDateTimePicker';");
                                        break;
                                    }
                                    case TIME:{
                                        dto.getQueryParams().add(
                                                new VueListTemDataDTO.QueryParamDTO(
                                                        Arrays.asList(fieldName+"_ge",fieldName+"_le" ),
                                                        comment,
                                                        "AkTimePicker",
                                                        ""
                                                ));
                                        dto.getQueryParamMap().put(fieldName+"_ge", new SpecConditionDTO("ge", "", field.getName()+"."+childField.getName()));
                                        dto.getQueryParamMap().put(fieldName+"_le", new SpecConditionDTO("le", "", field.getName()+"."+childField.getName()));
                                        dto.getImportComNames().add("AkTimePicker");
                                        dto.getImportComs().add("import AkTimePicker from '../../components/akfh/AkTimePicker';");
                                        break;
                                    }
                                    case BIGDECIMAL: {
                                        BigDecimal decimalStep = getDecimalStep(field.getMax(), field.getMin());

                                        dto.getQueryParams().add(
                                                new VueListTemDataDTO.QueryParamDTO(
                                                        Arrays.asList(fieldName+"_ge",fieldName+"_le" ),
                                                        comment,
                                                        "a-input-number",
                                                        Objects.isNull(decimalStep)?"":":step=\""+decimalStep.toPlainString()+"\""
                                                ));
                                        dto.getQueryParamMap().put(fieldName+"_ge", new SpecConditionDTO("ge", "", field.getName()+"."+childField.getName()));
                                        dto.getQueryParamMap().put(fieldName+"_le", new SpecConditionDTO("le", "", field.getName()+"."+childField.getName()));

                                        break;

                                    }
                                    case NUMBER:{
                                        dto.getQueryParams().add(
                                                new VueListTemDataDTO.QueryParamDTO(
                                                        Arrays.asList(fieldName+"_ge",fieldName+"_le" ),
                                                        comment,
                                                        "a-input-number",
                                                        ""
                                                ));
                                        dto.getQueryParamMap().put(fieldName+"_ge", new SpecConditionDTO("ge", "", field.getName()+"."+childField.getName()));
                                        dto.getQueryParamMap().put(fieldName+"_le", new SpecConditionDTO("le", "", field.getName()+"."+childField.getName()));

                                        break;
                                    }

                                    case TEXT:
                                    case TEXT_AREA:
                                    case RICH_TEXT:{
                                        dto.getQueryParams().add(
                                                new VueListTemDataDTO.QueryParamDTO(
                                                        Arrays.asList(fieldName ),
                                                        comment,
                                                        "a-input",
                                                        ""
                                                ));
                                        dto.getQueryParamMap().put(fieldName, new SpecConditionDTO("like", "", field.getName()+"."+childField.getName()));

                                        break;
                                    }

                                }

                            }
                        }
                    }
                }
            }
        }
        dto.setUrls(StringUtils.collectionToCommaDelimitedString(importUrlSet));
        return dto;
    }

    /**
     * 将实体类转换为实体生成模板数据
     * @param entity 实体类
     * @return
     */
    public static EntityTempDataDTO entityToEntityTempData(CodeGenClassEntity entity){
        EntityTempDataDTO dto = new EntityTempDataDTO();
        Set<String> importClassNames = new HashSet<>();
        dto.setEntityClass(getClassDTO(entity.getClassName()));
        dto.setTableName(entity.getTableName());
        dto.setSuperClass(getClassDTO(entity.getSuperClassName()));
        if(Objects.nonNull(dto.getSuperClass())){
            importClassNames.add(dto.getSuperClass().getClassName());
        }
        String interfaceClassNames = entity.getInterfaceClassNames();
        if(StringUtils.hasText(interfaceClassNames)){
            String[] interfaceClassNameArray = StringUtils.commaDelimitedListToStringArray(interfaceClassNames);
            for (String interfaceClassName : interfaceClassNameArray) {
                dto.getInterfaces().add(getClassDTO(interfaceClassName));
                importClassNames.add(interfaceClassName);
            }
        }
        dto.setComment(entity.getComment());


        List<CodeGenFieldEntity> fields = entity.getFields();
        for (CodeGenFieldEntity field : fields) {
            if(isIgnoreField(field.getName())){
                continue;
            }
            EntityTempDataDTO.FieldDTO fieldDTO = new EntityTempDataDTO.FieldDTO();
            String fieldClassName = field.getFieldClassName();
            fieldDTO.setFieldClass(getClassDTO(fieldClassName));
            ClassDTO collectionClassDTO = getClassDTO(field.getCollectionClassName());
            fieldDTO.setCollectionClass(collectionClassDTO);
            if(Objects.nonNull(collectionClassDTO)){
                importClassNames.add(collectionClassDTO.getClassName());
            }
            fieldDTO.setComment(field.getComment());
            fieldDTO.setName(field.getName());
            if(!fieldClassName.startsWith("java.lang.")){
                importClassNames.add(fieldClassName);
            }
            switch (field.getFieldType()){
                case BASIC:{
                    importClassNames.add(Column.class.getName());
                    fieldDTO.setColumnName(camelToUnderline(field.getName()));
                    fieldDTO.setUnique(field.getUnique());
                    fieldDTO.setRequired(field.getRequired());
                    fillBasicFieldDTO(fieldDTO, field);
                    if(fieldClassName.equals(BigDecimal.class.getName())){
                        BigDecimal max = field.getMax();
                        BigDecimal min = field.getMin();
                        Integer i = null, n = null;
                        if(Objects.nonNull(max)){
                            String maxStr = max.toPlainString();
                            int j = maxStr.lastIndexOf(".");
                            int i1 = j<0?maxStr.length():maxStr.substring(0, j).length();
                            int n1 = j<0?0:maxStr.substring(j+1).length();
                            i = i1;
                            n = n1;
                        }
                        if(Objects.nonNull(min)){
                            String minStr = min.toPlainString();
                            if(minStr.startsWith("-")){
                                minStr = minStr.substring(1);
                            }
                            int j = minStr.lastIndexOf(".");
                            int i1 = j<0?minStr.length():minStr.substring(0, j).length();
                            int n1 = j<0?0:minStr.substring(j+1).length();
                            if(Objects.isNull(i) || i< i1){
                                i = i1;
                            }
                            if(Objects.isNull(n) || n< n1){
                                n = n1;
                            }

                        }
                        if(Objects.nonNull(i)){
                            fieldDTO.setScale(n);
                            fieldDTO.setPrecision(i + n);
                        }
                    }
                    break;
                }
                case ENUM: {
                    importClassNames.add(Column.class.getName());
                    fieldDTO.setColumnName(camelToUnderline(field.getName()));
                    fieldDTO.setUnique(field.getUnique());
                    fieldDTO.setRequired(field.getRequired());
                    fillRequired(fieldDTO, field);
                    break;
                }
                case ENTITY:
                case COLLECTION: {
                    fillRequired(fieldDTO, field);
                    fieldDTO.setOneToMany(field.getOneToMany());
                    fieldDTO.setManyToMany(field.getManyToMany());
                    fieldDTO.setManyToOne(field.getManyToOne());
                    fieldDTO.setOneToOne(field.getOneToOne());
                    fieldDTO.setCascade(field.getCascade());
                    fieldDTO.setFetch(field.getFetch());
                    fieldDTO.setMappedBy(field.getMappedBy());
                    fieldDTO.setJoinTableName(field.getJoinTableName());
                    fieldDTO.setJoinTableJcName(field.getJoinTableJcName());
                    fieldDTO.setJoinTableIjcName(field.getJoinTableIjcName());
                    fieldDTO.setJoinColumnName(field.getJoinColumnName());
                    if(Objects.nonNull(fieldDTO.getOneToMany()) && fieldDTO.getOneToMany()){
                        importClassNames.add(OneToMany.class.getName());
                    }
                    if(Objects.nonNull(fieldDTO.getManyToMany()) && fieldDTO.getManyToMany()){
                        importClassNames.add(ManyToMany.class.getName());
                    }
                    if(Objects.nonNull(fieldDTO.getManyToOne()) && fieldDTO.getManyToOne()){
                        importClassNames.add(ManyToOne.class.getName());
                    }
                    if(Objects.nonNull(fieldDTO.getOneToOne()) && fieldDTO.getOneToOne()){
                        importClassNames.add(OneToOne.class.getName());
                    }
                    if(StringUtils.hasText(fieldDTO.getCascade())){
                        importClassNames.add(CascadeType.class.getName());
                    }
                    if(StringUtils.hasText(fieldDTO.getFetch())){
                        importClassNames.add(FetchType.class.getName());
                    }
                    if(StringUtils.hasText(fieldDTO.getJoinColumnName())
                            ||StringUtils.hasText(fieldDTO.getJoinTableIjcName())
                            ||StringUtils.hasText(fieldDTO.getJoinTableJcName())){
                        importClassNames.add(JoinColumn.class.getName());
                    }
                    if(StringUtils.hasText(fieldDTO.getJoinTableName())){
                        importClassNames.add(JoinTable.class.getName());
                    }
                    break;
                }
            }

             dto.getImportClass().addAll(fieldDTO.getImportClassNames());

            dto.getFields().add(fieldDTO);
        }
        importClassNames.add(Entity.class.getName());
        importClassNames.add(Table.class.getName());
        importClassNames.add(Getter.class.getName());
        importClassNames.add(Setter.class.getName());
        dto.getImportClass().addAll(importClassNames);
        Collections.sort(dto.getImportClass());
        return dto;
    }



    /**
     * 将实体类转换为repository生成模板数据
     * @param entity 实体类
     * @return
     */
    public static RepositoryTempDataDTO entityToRepositoryTempData(CodeGenClassEntity entity){
        RepositoryTempDataDTO dto = new RepositoryTempDataDTO();
        dto.setEntityClass(getClassDTO(entity.getClassName()));
        dto.setRepositoryClass(getClassDTO(dto.getEntityClass().getPackageName().replace(".domain.entity", "")

        +".repository."+getSubEntitySuffixName(entity.getClassName())+"Repository"
        ));
        dto.setComment(entity.getComment());
        Set<String> im = new HashSet<>();
        im.add(Repository.class.getName());
        im.add(entity.getClassName());
        im.add(JpaRepositoryImplementation.class.getName());
        List<String> importClass = dto.getImportClass();
        importClass.addAll(im);
        Collections.sort(importClass);
        return dto;

    }
    /**
     * 将实体类转换为repository生成模板数据
     * @param entity 实体类
     * @return
     */
    public static ServiceTempDataDTO entityToServiceTempData(CodeGenClassEntity entity){
        ServiceTempDataDTO dto = new ServiceTempDataDTO();
        dto.setEntityClass(getClassDTO(entity.getClassName()));
        dto.setServiceClass(getClassDTO(dto.getEntityClass().getPackageName().replace(".domain.entity", "")

                +".service."+getSubEntitySuffixName(entity.getClassName())+"Service"
        ));
        Set<String> im = new HashSet<>();
        dto.setComment(entity.getComment());
       if(isTreeEntity(entity.getClassName())){
            dto.setSuperClass(getClassDTO(BaseTreeService.class.getName()));
            im.add(BaseTreeService.class.getName());
        }else {
            dto.setSuperClass(getClassDTO(BaseService.class.getName()));
            im.add(BaseService.class.getName());
        }

        im.add(entity.getClassName());
        im.add(DictEntityService.class.getName());
        List<String> importClass = dto.getImportClass();
        importClass.addAll(im);
        Collections.sort(importClass);
        return dto;

    }


    public static ServiceImplTempDataDTO buildServiceImplTempDataDTO(EntityTempDataDTO entityTempDataDTO,
                                                                     RepositoryTempDataDTO repositoryTempDataDTO,
                                                                     ServiceTempDataDTO serviceTempDataDTO,
                                                                     AddTempDataDTO addTempDataDTO,
                                                                     EditTempDataDTO editTempDataDTO,
                                                                     ExcelTempDataDTO excelTempDataDTO,
                                                                     CodeGenClassEntity entity){
        Set<String> importClass = new HashSet<>();
        ServiceImplTempDataDTO dto = new ServiceImplTempDataDTO();
        dto.setEntityClass(entityTempDataDTO.getEntityClass());
        importClass.add(dto.getEntityClass().getClassName());

        dto.setServiceClass(serviceTempDataDTO.getServiceClass());
        importClass.add(dto.getServiceClass().getClassName());

        dto.setRepositoryClass(repositoryTempDataDTO.getRepositoryClass());
        importClass.add(dto.getRepositoryClass().getClassName());

        dto.setAddClass(addTempDataDTO.getAddClass());
        importClass.add(dto.getAddClass().getClassName());

        dto.setEditClass(editTempDataDTO.getEditClass());
        importClass.add(dto.getEditClass().getClassName());

        dto.setExcelClass(excelTempDataDTO.getExcelClass());
        importClass.add(dto.getExcelClass().getClassName());

        importClass.add(Autowired.class.getName());
        importClass.add(org.springframework.stereotype.Service.class.getName());
        importClass.add(Validated.class.getName());
        importClass.add(EditPDTO.class.getName());
        importClass.add(JpaRepositoryImplementation.class.getName());


        dto.setComment(entity.getComment());
        if(isTreeEntity(entity.getClassName())){
            dto.setExcelModalDTO("BaseTreeExcelModalDTO");
            importClass.add(BaseTreeExcelModalDTO.class.getName());
            dto.setSuperClass(getClassDTO(JpaTreeService.class.getName()));
            importClass.add(JpaTreeService.class.getName());
        }else  {
            dto.setExcelModalDTO("BaseExcelModalDTO");
            importClass.add(BaseExcelModalDTO.class.getName());
            dto.setSuperClass(getClassDTO(JpaService.class.getName()));
            importClass.add(JpaService.class.getName());
        }

        for (CodeGenFieldEntity field : entity.getFields()) {
            Boolean excelId = field.getExcelId();
            if(Objects.nonNull(excelId) && excelId){
                dto.setExcelEntityIdField(field.getName());
            }
            if(field.getFieldType().equals(FieldTypeEnum.COLLECTION) && StringUtils.hasText(field.getExcelEmbedId())){
                dto.setExcelEmbedIds(AkUtils.megerFieldName(field.getName(), field.getExcelEmbedId(), true));
            }else if(field.getFieldType().equals(FieldTypeEnum.ENTITY) && StringUtils.hasText(field.getExcelEmbedId())){
                dto.setExcelEmbedIds(AkUtils.megerFieldName(field.getName(), field.getExcelEmbedId(), false));
            }
        }

        dto.setServiceImplClass(getClassDTO(
                dto.getEntityClass().getPackageName().replace(".domain.entity", "")

                        +".service.impl."+getSubEntitySuffixName(entity.getClassName())+"ServiceImpl"
        ));
        dto.getImportClass().addAll(importClass);
        Collections.sort(dto.getImportClass());

        return dto;
    }


    private static String getSubEntitySuffixName(String entityClassName){
        String str = entityClassName.substring(entityClassName.lastIndexOf(".")+1);
        if(str.endsWith("Entity")){
            return str.substring(0, str.length()-"Entity".length());
        }
        return str;
    }

    /**
     * 驼峰转下划线
     * @param text 文本
     * @return 转下划线文本
     */
    private static String camelToUnderline(String text){
        StringBuilder builder = new StringBuilder(text.replace('.', '_'));
        for (int i = 1; i < builder.length() - 1; i++) {
            if(Character.isLowerCase(builder.charAt(i - 1)) && Character.isUpperCase(builder.charAt(i)) && Character.isLowerCase(builder.charAt(i + 1))){
                builder.insert(i++, '_');
            }
        }
        return builder.toString();

    }


    public static ClassDTO getClassDTO(String className){
        if(!StringUtils.hasText(className)){
            return null;
        }
        return new ClassDTO(className);
    }

    public static String getPackageName(String className){
        if(!StringUtils.hasText(className)){
            return null;
        }
        int i = className.lastIndexOf(".");
        if(i<=0){
            return "";
        }
        return className.substring(0, i);
    }

    public static String getClassSimpleName(String className){
        if(!StringUtils.hasText(className)){
            return null;
        }
        return className.substring(className.lastIndexOf(".")+1);
    }
}
